/*********************************************************************************
 *       Filename:  main.c
 *    Description:  该文件实现了客户端的主逻辑函数，主要功能包括：
 *                  1. 定期从温度传感器（DS18B20）采集温度数据。
 *                  2. 将采集到的数据通过套接字连接传输到服务器。
 *                  3. 如果连接丢失，则将数据保存到本地数据库，并在连接恢复时重新发送数据。
 *                  4. 支持通过命令行参数配置服务器 IP、端口、采样时间。          
 *
 *        Version:  1.0.0(2024/11/28 10:37:00)
 *         Author:  Zhang Long <1318085470@qq.com>
 *      ChangeLog:  1, Release initial version on "2024/11/28 10:37:00"
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <sqlite3.h>

#include "database.h"
#include "ds18b20.h"
#include "transferdata.h"
#include "localtime.h"
#include "socket.h"

struct option		opts[] =
{
	{"ipaddr", required_argument, NULL, 'i'},
	{"port", required_argument, NULL, 'p'},
	{"time", required_argument, NULL, 't'},
	{"debug", no_argument, NULL, 'd'},
	{"help", no_argument, NULL, 'h'},
	{NULL, 0, NULL, 0}
};

void print_usage(char *progname)
{
	printf("%s usage: \n", progname);
	printf("-i(--ipaddr): specify server IP address\n");
	printf("-p(--port):   specify server PORT\n");
	printf("-t(--time):   specify sample time of temperature(also not specify, default is 3s)\n");
	printf("-d(--debug):  specify program running in debug mode\n");
	printf("-h(--help):   print this help information\n");

	printf("\nExample: %s -i 127.0.0.1 -p 12345 -t 2 -d\n", progname);

	return ;
}

int main(int argc, char **argv)
{
	int 			   ch;
	char  			   *server_ip = NULL;	 	
	int				   server_port = 0;

	char		       sql[256] = {0};
	char		       sql_select[256] = {0};
	int                rc;
	const char         *sql_select_data = "SELECT * FROM temperature;";
	sqlite3			   *db;
	char			   *db_file = "client.db";
	sqlite3_stmt       *stmt;
	int                db_nums;
	float              temp;
	int                rv;
	packet_t		   pack = {0};
	char			   pack_buf[1024] = {0};
	int				   over_ds18b20_flag  = 0;
	time_t			   last_sample_time = 0;
	time_t			   last_connect_time = 0;
	int				   sample_time = 3;
	char			   *progname = NULL;
	int                daemon_run = 0;
	socket_t		   sock = {0};


	progname = basename(argv[0]);
	while ( -1 != (ch=getopt_long(argc, argv, "i:p:t:dh", opts, NULL)) )
	{
		switch (ch)
		{
			case 'i':
				server_ip = optarg;
				break;

			case 'p':
				server_port = atoi(optarg);
				break;

			case 't':
				sample_time = atoi(optarg);
				break;

			case 'd':
				daemon_run=1;
				break;

			case 'h':
				print_usage(progname);
				return 0;

			default:
				return -1;
		}
	}
	if( daemon_run )
	{
		daemon(0, 0);
	}



	db_open(&db, db_file);
	printf(" db_open over.\n");
	db_create(db,TA_CREATE);
	printf(" db_create over.\n");


#if  0
	rc = sqlite3_prepare_v2(db, sql_select_data, -1, &stmt, 0);

	printf("COUNT\tID\tTIME\t\t\tTEMP\n");
	printf("-----------------------------------------------\n");


	while (sqlite3_step(stmt) == SQLITE_ROW)
	{

		int count = sqlite3_column_int(stmt, 0);                       // 获取 COUNT 列（INTEGER 类型）
		const unsigned char *id = sqlite3_column_text(stmt, 1);        // 获取 ID 列（TEXT 类型）
		const unsigned char *time = sqlite3_column_text(stmt, 2);      // 获取 TIME 列（DATETIME 类型）
		float temp = sqlite3_column_double(stmt, 3);                  // 获取 TEMP 列（REAL 类型）

		// 打印结果，确保处理 NULL 数据
		printf("%d\t%s\t%s\t%.4f\n", 
				count, 
				id ? (const char *)id : "NULL", 
				time ? (const char *)time : "NULL", 
				temp);
	}
#endif
	socket_init(&sock, server_ip, server_port);
	sock.fd=-1;
	while(1)
	{
		over_ds18b20_flag = 0;

		if (interval_timer(&last_sample_time, 3))
		{
			if (sample_and_package_temperature(&pack))
			{
				printf("sample_and_package_temperature() error\n");
				continue;
			}
			printf("Get data ok: ID[%s] TIME[%s] TEMP[%.2f]\n", pack.id, pack.time, pack.temp);

			over_ds18b20_flag = 1;
		}

		//if( socket_check_connect(sock.fd) <0)
		if (sock.fd < 0)
		{
			sleep(1);
			if (socket_connect(&sock) >= 0)
				printf("Connect to server[%s:%d] ok\n", sock.host, sock.port);
		}


		if(socket_check_connect(sock.fd) < 0)  
		{
			socket_close(&sock);
			if (over_ds18b20_flag)
			{
				write_to_db(db, &pack);
			}
			//sleep(1);
			continue;
		}

		if( over_ds18b20_flag )
		{
			if (over_ds18b20_flag)
			{
				format_packet_data(&pack, pack_buf, sizeof(pack_buf));

				if ( (rv=socket_write(sock.fd, pack_buf, strlen(pack_buf))) < 0 )
				{
					printf("Client write data to Server failure and save it in database\n");
					write_to_db(db, &pack);
					socket_close(&sock);
				}
				printf("Write %d bytes data[%s] to server[%s:%d] ok\n", rv, pack_buf, sock.host, sock.port);
			}
		}

		if (db_count(db) > 0)
		{
			read_from_db(db, &pack);
			format_packet_data(&pack, pack_buf, sizeof(pack_buf));

			if ( (rv=socket_write(sock.fd, pack_buf, strlen(pack_buf))) < 0 )
			{
				printf("Client write data to Server failure and save it in database\n");
				write_to_db(db, &pack);
				socket_close(&sock);
			}
		}
	}



	socket_close(&sock);
	sqlite3_finalize(stmt);
	db_close(db, db_file);
	return 0;
}

